# -*- coding: utf8 -*-
from multiprocessing import Pool
from .beidou_northeast_hemisphere import beidou_grid_encoding
from .beidou_northeast_hemisphere import transform_longitude_latitude
import os
from lat_lon_parser import parse
# import sys
# sys.setrecursionlimit(1000000)


# def generate_grid_code_from_two_points(point1, point2, level_n):
#     """
#     通过二分法打点法，完成两点之间网格的北斗网格
#     :param point1:
#     :param point2:
#     :param level_n:
#     :return:
#     """
#     longtitude1, latitude1, point1code = point1
#     longtitude2, latitude2, point2code = point2
#     if point1code is None:
#         point1code = beidou_grid_encoding(longtitude1, latitude1, level_n)
#         point1[2] = point1code
#     if point2code is None:
#         point2code = beidou_grid_encoding(longtitude2, latitude2, level_n)
#         point2[2] = point2code
#     if point1code == point2code:
#         return [point1, point2]
#     else:
#         longtitude_mid, latitude_mid = (longtitude1 + longtitude2) / 2, (latitude1 + latitude2) / 2
#         pointmidcode = beidou_grid_encoding(longtitude_mid, latitude_mid, level_n)
#         point_mid = [longtitude_mid, latitude_mid, pointmidcode]
#         return generate_grid_code_from_two_points(point1, point_mid, level_n) + generate_grid_code_from_two_points(
#             point_mid, point2, level_n)


def generate_grid_code_from_two_points(point1, point2, level_n):
    """
    通过二分法打点法，完成两点之间网格的北斗网格
    :param point1:
    :param point2:
    :param level_n:
    :return:
    """
    longtitude1, latitude1, point1code = point1
    longtitude2, latitude2, point2code = point2
    if point1code is None:
        point1code = beidou_grid_encoding(longtitude1, latitude1, level_n)
        point1[2] = point1code
    if point2code is None:
        point2code = beidou_grid_encoding(longtitude2, latitude2, level_n)
        point2[2] = point2code
    if point1code == point2code:
        return [point1, point2]
    else:
        longtitude_split_list = [longtitude1,longtitude2]
        latitude_split_list = [latitude1,latitude2]
        point_grid_code_split_list = [point1,point2]
        point3 = [longtitude2, latitude2, point2code]
        # print(point_grid_code_split_list)
        while True:
            longtitude_mid, latitude_mid = (point1[0] + point3[0]) / 2.0, (point1[1] + point3[1]) / 2.0
            point_mid_code = beidou_grid_encoding(longtitude_mid, latitude_mid, level_n)
            # 对线段继续进行二等分
            for i in range(len(longtitude_split_list) - 1, 0, -1):
                long_split = (longtitude_split_list[i] + longtitude_split_list[i-1])/2.0
                lat_split = (latitude_split_list[i] + latitude_split_list[i-1])/2.0
                point_split = [long_split, lat_split, beidou_grid_encoding(long_split, lat_split, level_n)]
                longtitude_split_list.insert(i, long_split)
                latitude_split_list.insert(i, lat_split)
                point_grid_code_split_list.insert(i, point_split)
            # print(point_grid_code_split_list)
            if point1[2] == point_mid_code:
                # 切分完这一次就ok了
                break
            else:
                point3 = [longtitude_mid, latitude_mid, point_mid_code]
        return point_grid_code_split_list


def beidou_grid_code_line(longitudeList, latitudeList, level_n, parralel=False):
    """
    给出平面上一条线的经纬度表示，构造成点。要求经纬度以字符串样式传入，并且逗号分割。经纬度相对应 (long1,lat1),(long2,lat2),(long3,lat3)
    :param longitudeList: str , seperator ; ,demo: "long1;long2;long3"
    :param latitudeList: str , seperator ; ,demo: "lat1;lat2;lat3"
    :param level_n: int , [1,10]
    :return:
    """
    longitude_list = longitudeList.split(';')
    latitude_ist = latitudeList.split(';')
    try:
        assert len(longitude_list) == len(latitude_ist)
    except:
        raise Exception(f'parse argument error,please check,{longitudeList}||{latitudeList}')
    else:
        for longitude, latitude in zip(longitude_list, latitude_ist):
            point = (longitude, latitude)
            # print(point)
            try:
                longitude_float = parse(longitude)
                latitude_float = parse(latitude)
            except:
                raise Exception(f'point format error,please check point {point}')
            else:
                try:
                    assert longitude_float >= 0 and latitude_float >= 0
                except:
                    raise Exception(f'只能处理东北半球的经纬度点，{point}')
    # format longitude and latitude
    point_list_format = [[transform_longitude_latitude(longitude), transform_longitude_latitude(latitude), None] for
                         longitude, latitude in zip(longitude_list, latitude_ist)]
    # print(point_list_format)
    # 并行处理或单步处理
    if parralel:
        pool = Pool(os.cpu_count())
        results = []
        for i in range(len(point_list_format) - 1):
            point1 = point_list_format[i]
            point2 = point_list_format[i + 1]
            res = pool.apply_async(generate_grid_code_from_two_points, args=(point1, point2, level_n))
            results.append(res)
        pool.close()
        pool.join()
        grid_code_result = [res.get() for res in results]
        pool.terminate()
        grid_code_list = [result[2] for result in grid_code_result for point in result]
    else:
        grid_code_result = [generate_grid_code_from_two_points(point_list_format[i], point_list_format[i + 1], level_n)
                            for i in range(len(point_list_format) - 1)]
        grid_code_list = [point[2] for result in grid_code_result for point in result]

    grid_code_set = list(set(grid_code_list))
    return grid_code_set


if __name__ == '__main__':
    # point1 = [longtitude1,latitude1,None]
    # point2 = [longtitude1, latitude1, None]
    # level_n = n
    pass
